let http = require("http");
let fs = require("fs");
let path = require("path");
let connect = require("./sql");
let url = require("url");
let formidable = require("formidable");
let socket = require("socket.io");
let zlib = require("zlib");
let stream = require("stream");
let { chatai } = require("./ai/dsai.js");
let inter = null;
let app = http.createServer((req, res) => {
  // res.setHeader("Content-Type", "text/plain;charset=utf8")
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader("Access-Control-Allow-Headers", "X-Requested-With");
  //允许的header类型
  res.setHeader(
    "Access-Control-Allow-Headers",
    "Origin,X-Requested-With,Accept,Content-type"
  );
  res.setHeader("Access-Control-Allow-Credentials", true);
  //跨域允许的请求方式
  res.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
  // res.setHeader("Content-Type", "application/json;charset=utf-8");
  let rurl = url.parse(req.url).pathname;
  app.req = req;
  app.res = res;
  switch (rurl) {
    case "/":
      res.setHeader("Content-Type", "text/html;charset=utf8");
      let html = fs.readFileSync(path.join(__dirname, "static/index.html"));
      const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress;
      console.log(`您的IP地址是: ${ip}`);
      app.use((req, res) => {
        // console.log("自定义中间件", res);
      });
      res.write(html);
      res.end();
      break;
    case "/chat":
      res.setHeader("Content-Type", "text/html;charset=utf8");
      let html1 = fs.readFileSync(
        path.join(__dirname, "static/websocket.html")
      );
      res.write(html1);
      res.end();
      break;
    case "/zb":
      res.setHeader("Content-Type", "text/html;charset=utf8");
      let html2 = fs.readFileSync(path.join(__dirname, "static/lp.html"));
      res.write(html2);
      res.end();
      break;
    case "/mp3":
      try {
        let p = fs.createReadStream(path.join(__dirname, "./static/aa.mp3"));
        p.pipe(res);
      } catch (e) {
        console.log("文件传输失败" + e);
        res.end("文件不传承");
      }
      break;
    case "/mp4":
      res.setHeader("Content-Type", "video/mp4");
      try {
        let p = fs.createReadStream(path.join(__dirname, "./uploads/zb.mp4"));
        p.pipe(res);
      } catch (e) {
        console.log("文件传输失败" + e);
        res.end("文件不传承");
      }
      break;
    case "/query":
      try {
        connect.query("select * from tt", (err, result) => {
          if (err) {
            res.statusCode = 500;
            return res.end("查询数据错误" + err);
          }
          res.write(JSON.stringify(result));
          res.end();
        });
      } catch (e) {
        res.statusCode = 500;
        res.end("服务器错误" + e);
      }
      break;
    case "/sa":
      let obj1 = parseObj(req);
      connect.query(
        "select * from t1 where age=? and id=?",
        [obj1.age, obj1.id],
        (err, result) => {
          if (err) {
            res.statusCode = 500;
            return res.end("发生错误" + err);
          }
          res.write(JSON.stringify(result));
          res.end();
        }
      );
      break;
    case "/insert":
      let obj2 = parseObj(req);
      connect.query(
        "insert into t1(name,age,des) values (?,?,?)",
        [obj2.name, obj2.age, obj2.des],
        async (err, result) => {
          if (err) {
            res.statusCode = 500;
            res.end("错误" + err);
            return;
          }

          let [rows] = await connect
            .promise()
            .query("select id,name,age,des from t1 where name=? and age=?", [
              obj2.name,
              obj2.age,
            ]);
          res.write(JSON.stringify(rows));
          res.end();
        }
      );
      break;
    case "/del":
      let obj3 = parseObj(req);
      connect.query("delete from t1 where id=?", [obj3.id], (err, result) => {
        if (err) {
          res.statusCode = 500;
          res.end("错误" + err);
          return;
        }
        res.write(
          JSON.stringify({
            code: 200,
            message: `id=${obj3.id} 的数据删除成功`,
          })
        );
        res.end();
      });
      break;
    case "/update":
      let obj4 = parseObj(req);
      connect.query(
        "update t1 set age=? where id=?",
        [obj4.age, obj4.id],
        async (err, result) => {
          if (err) {
            sendErr(res, err);
            return;
          }
          let [rows] = await connect
            .promise()
            .query("select id,name,age from t1 where id=?", [obj4.id]);
          res.write(JSON.stringify(rows));
          res.end();
        }
      );
      break;
    case "/upload":
      try {
        let form = new formidable.IncomingForm();
        form.keepExtensions = true;
        form.uploadDir = path.join(__dirname, "uploads");
        form.parse(req, (err, fields, files) => {
          if (err) {
            sendErr(res, err, 400);
            return;
          }
          console.log(fields, "fields");
          console.log(files, "files");
          try {
            let oldpath = files.attrName.filepath;
            let newpath =
              path.dirname(oldpath) + "/" + files.attrName.originalFilename;
            fs.renameSync(oldpath, newpath);

            res.write(
              JSON.stringify({
                code: 200,
                message: {
                  name: files.attrName.originalFilename,
                  path: newpath,
                },
              })
            );
            res.end();
          } catch (err) {
            sendErr(res, err);
          }
        });
      } catch (err) {
        sendErr(res, err);
      }

      break;
    case "/zlip":
      res.setHeader("content-encoding", "gzip");
      try {
        let gz = zlib.createGzip();
        let fl = fs.createReadStream(path.join(__dirname, "./static/a.txt"));
        fl.pipe(gz).pipe(res);
      } catch (err) {
        sendErr(res, err);
      }
      break;
    case "/sse":
      inter && clearInterval(inter);
      try {
        res.writeHead(200, {
          "Content-Type": "text/event-stream",
          "Cache-Control": "no-cache",
          Connection: "keep-alive",
        });
        let counter = 1;
        inter = setInterval(() => {
          res.write(`event: message\n`);
          res.write(
            `data: 使用EventSource/sse--推送数据-这是第${counter}次推送\n\n`
          );
          counter++;
          if (counter > 10) {
            clearInterval(inter);
          }
        }, 5000);
      } catch (err) {
        sendErr(res, err);
        clearInterval(inter);
      }
      break;
    case "/sse2":
      res.writeHead(200, {
        "Content-Type": "text/event-stream",
        "Cache-Control": "no-cache",
        Connection: "keep-alive",
      });
      function sendFileChunks() {
        let index = 0;
        const sendChunk = () => {
          if (index >= 10) {
            //  res.write('event: end\ndata: \n\n'); // 发送结束事件
            res.end();
            return;
          }
          chunk =
            Math.random().toString(16).slice(2, 8) +
            "--sse/ReadableStream数据推送 \n";
          // SSE 格式要求
          res.write(`data: ${JSON.stringify({ text: chunk })}\n`);
          index += 1;
          // 随机间隔发送（模拟实时效果）
          setTimeout(sendChunk, 1000 + Math.random() * 500);
        };

        sendChunk();
      }
      sendFileChunks();

      break;
    default:
      res.statusCode = 400;
      res.end(req.url + "路径错误");
  }
});

app.on("close", (err) => {
  inter && clearInterval(inter);
});

app.use = function (fn) {
  fn(app.req, app.res);
};
app.listen("7012", () => {
  console.log("7012端口已开启");
});
let io = socket(app, { cors: true });
let user = [];
io.on("connection", (scok) => {
  // scok.emit() ：向建立该连接的客户端广播   给自己发
  // scok.broadcast.emit() ：向除去建立该连接的客户端的所有客户端广播,不给自己
  // io.sockets.emit() ： 向所有客户端广播，等同于上面两个的和  给所有人发包括自己
  scok.on("disconnect", (mess) => {
    user = user.filter((item) => item.id != scok.id);
    scok.broadcast.emit("logout", { user, logoutid: scok.id });
  });
  scok.on("error", (err) => {
    console.log(err, "连接发生错误");
  });
  scok.on("message", (data) => {
    console.log(data, "接收到信息");
    let u = user.filter((item) => item.id == scok.id)[0];
    //scok.emit('message', { time: new Date(), message: Math.random().toString(16).slice(2, 8) })

    scok.broadcast.emit("message", {
      userid: u?.userid,
      message: data.message,
      id: u?.id,
    });
  });
  scok.on("sayTo", (data) => {
    //socket.emit('message', {id:socket.id,message:toMsg})
    let id = data.id,
      msg = data.message;
    console.log("io.sockets.sockets", data);
    let toscok = [...io.sockets.sockets].filter((item) => {
      console.log(item, "dddddddd");
      return item[1].id == id;
    })?.[0]?.[1];
    console.log(toscok, "toscok");
    toscok?.emit("message", { id: id, message: msg });
  });
  scok.on("chatai", async (data) => {
    let msg = data.message;
    let res = await chatai(msg);
    for await (const chunk of res) {
      scok.emit("chatai", { message: chunk.choices[0]?.delta?.content ?? "" });
    }
    scok.emit("chatai", { message: "</stop>" });
  });
  scok.on("login", (data) => {
    let newuser = {
      userid: data,
      id: scok.id,
    };
    user.push(newuser);
    let u = user.filter((item) => item.id != scok.id);
    scok.emit("login", scok.id); //给自己发 id
    scok.emit("userLs", u); //给自己发目前在线人数
    scok.broadcast.emit("userLs", [newuser]); //向其他用户发自己上线了
  });

  //录屏

  let writeStream = fs.createWriteStream(
    path.join(__dirname, "./uploads/zb.mp4")
  );

  writeStream.on("finish", function () {
    console.log("写入完成");
  });

  scok.on("sjl", (data) => {
    //2.设置写入流的字符集：先写入缓存
    writeStream.write(data);

    // 创建一个bufferstream
    // var bufferStream = new stream(data);
    //将Buffer写入
  });
  scok.on("zb-stop", () => {
    //3.写入结束
    writeStream.end();
  });
  scok.on("lb", async () => {
    let f = await fs.readFileSync(path.join(__dirname, "./uploads/zb.mp4"));
    scok.emit("lb-hf", f);
  });
});
function parseObj(req) {
  let query = url.parse(req.url).query;
  let params = query.split("&");
  let obj = {};
  params.forEach((p) => {
    obj[p.split("=")[0]] = p.split("=")[1];
  });
  return obj;
}

function sendErr(res, err, code = 500) {
  res.statusCode = code;
  res.end("发生错误" + err);
}

async function cc() {
  let res = await chatai("你好");
  for await (const chunk of res) {
    // console.log(chunk.choices[0].message.content);
    console.log(chunk.choices[0]?.delta?.content);
  }
}
